home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 2003 August / MW 8 2003 CD1.iso / Inside Macworld / Product News / gimp-1.2.4.sit / gimp-1.2.4 / app / levels.c < prev    next >
Encoding:
C/C++ Source or Header  |  2003-05-12  |  42.1 KB  |  1,618 lines

  1. /* The GIMP -- an image manipulation program
  2.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  3.  *
  4.  * This program is free software; you can redistribute it and/or modify
  5.  * it under the terms of the GNU General Public License as published by
  6.  * the Free Software Foundation; either version 2 of the License, or
  7.  * (at your option) any later version.
  8.  *
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17.  */
  18.  
  19. #include "config.h"
  20.  
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include <errno.h>
  25.  
  26. #include <glib.h>
  27.  
  28. #include "apptypes.h"
  29.  
  30. #include "appenv.h"
  31. #include "drawable.h"
  32. #include "gdisplay.h"
  33. #include "histogramwidget.h"
  34. #include "gimphistogram.h"
  35. #include "gimpui.h"
  36. #include "image_map.h"
  37. #include "levels.h"
  38. #include "gimplut.h"
  39. #include "lut_funcs.h"
  40.  
  41. #include "libgimp/gimpenv.h"
  42. #include "libgimp/gimpmath.h"
  43.  
  44. #include "libgimp/gimpintl.h"
  45.  
  46. #define LOW_INPUT          0x1
  47. #define GAMMA              0x2
  48. #define HIGH_INPUT         0x4
  49. #define LOW_OUTPUT         0x8
  50. #define HIGH_OUTPUT        0x10
  51. #define INPUT_LEVELS       0x20
  52. #define OUTPUT_LEVELS      0x40
  53. #define INPUT_SLIDERS      0x80
  54. #define OUTPUT_SLIDERS     0x100
  55. #define DRAW               0x200
  56. #define ALL                0xFFF
  57.  
  58. #define DA_WIDTH         256
  59. #define DA_HEIGHT        25
  60. #define GRADIENT_HEIGHT  15
  61. #define CONTROL_HEIGHT   DA_HEIGHT - GRADIENT_HEIGHT
  62. #define HISTOGRAM_WIDTH  256
  63. #define HISTOGRAM_HEIGHT 150
  64.  
  65. #define LEVELS_DA_MASK  GDK_EXPOSURE_MASK | \
  66.                         GDK_ENTER_NOTIFY_MASK | \
  67.             GDK_BUTTON_PRESS_MASK | \
  68.             GDK_BUTTON_RELEASE_MASK | \
  69.             GDK_BUTTON1_MOTION_MASK | \
  70.             GDK_POINTER_MOTION_HINT_MASK
  71.  
  72. /*  the levels structures  */
  73.  
  74. typedef struct _Levels Levels;
  75.  
  76. struct _Levels
  77. {
  78.   gint x, y;    /*  coords for last mouse click  */
  79. };
  80.  
  81. typedef struct _LevelsDialog LevelsDialog;
  82.  
  83. struct _LevelsDialog
  84. {
  85.   GtkWidget       *shell;
  86.  
  87.   GtkAdjustment   *low_input_data;
  88.   GtkAdjustment   *gamma_data;
  89.   GtkAdjustment   *high_input_data;
  90.   GtkAdjustment   *low_output_data;
  91.   GtkAdjustment   *high_output_data;
  92.  
  93.   GtkWidget       *input_levels_da[2];
  94.   GtkWidget       *output_levels_da[2];
  95.   GtkWidget       *channel_menu;
  96.  
  97.   HistogramWidget *histogram;
  98.   GimpHistogram   *hist;
  99.  
  100.   GimpDrawable   *drawable;
  101.  
  102.   ImageMap        image_map;
  103.  
  104.   gint            color;
  105.   gint            channel;
  106.   gint            low_input[5];
  107.   gdouble         gamma[5];
  108.   gint            high_input[5];
  109.   gint            low_output[5];
  110.   gint            high_output[5];
  111.   gboolean        preview;
  112.  
  113.   gint            active_slider;
  114.   gint            slider_pos[5];  /*  positions for the five sliders  */
  115.  
  116.   guchar          input[5][256]; /* this is used only by the gui */
  117.  
  118.   GimpLut        *lut;
  119.  
  120.   glong           conn_id;
  121. };
  122.  
  123. /*  the levels tool options  */
  124. static ToolOptions *levels_options = NULL;
  125.  
  126. /*  the levels tool dialog  */
  127. static LevelsDialog *levels_dialog = NULL;
  128.  
  129. /*  the levels file dialog  */
  130. static GtkWidget *file_dlg = NULL;
  131. static gboolean   load_save;
  132.  
  133. static GtkWidget *color_option_items[5];
  134.  
  135. /*  levels action functions  */
  136. static void   levels_control (Tool *, ToolAction, gpointer);
  137.  
  138. static LevelsDialog * levels_dialog_new (void);
  139.  
  140. static void   levels_calculate_transfers           (LevelsDialog *);
  141. static void   levels_update                        (LevelsDialog *, gint);
  142. static void   levels_preview                       (LevelsDialog *);
  143. static void   levels_channel_callback              (GtkWidget *, gpointer);
  144. static void   levels_reset_callback                (GtkWidget *, gpointer);
  145. static void   levels_ok_callback                   (GtkWidget *, gpointer);
  146. static void   levels_cancel_callback               (GtkWidget *, gpointer);
  147. static void   levels_auto_callback                 (GtkWidget *, gpointer);
  148. static void   levels_load_callback                 (GtkWidget *, gpointer);
  149. static void   levels_save_callback                 (GtkWidget *, gpointer);
  150. static void   levels_preview_update                (GtkWidget *, gpointer);
  151. static void   levels_low_input_adjustment_update   (GtkAdjustment *, gpointer);
  152. static void   levels_gamma_adjustment_update       (GtkAdjustment *, gpointer);
  153. static void   levels_high_input_adjustment_update  (GtkAdjustment *, gpointer);
  154. static void   levels_low_output_adjustment_update  (GtkAdjustment *, gpointer);
  155. static void   levels_high_output_adjustment_update (GtkAdjustment *, gpointer);
  156. static gint   levels_input_da_events               (GtkWidget *, GdkEvent *, 
  157.                             LevelsDialog *);
  158. static gint   levels_output_da_events              (GtkWidget *, GdkEvent *,
  159.                             LevelsDialog *);
  160.  
  161. static void   file_dialog_create                   (GtkWidget *);
  162. static void   file_dialog_ok_callback              (GtkWidget *, gpointer);
  163. static void   file_dialog_cancel_callback          (GtkWidget *, gpointer);
  164.  
  165. static gboolean  levels_read_from_file             (FILE *f);
  166. static void      levels_write_to_file              (FILE *f);
  167.  
  168.  
  169. /*  levels action functions  */
  170.  
  171. static void
  172. levels_control (Tool       *tool,
  173.         ToolAction  action,
  174.         gpointer    gdisp_ptr)
  175. {
  176.   switch (action)
  177.     {
  178.     case PAUSE:
  179.       break;
  180.  
  181.     case RESUME:
  182.       break;
  183.  
  184.     case HALT:
  185.       levels_dialog_hide ();
  186.       break;
  187.  
  188.     default:
  189.       break;
  190.     }
  191. }
  192.  
  193. Tool *
  194. tools_new_levels (void)
  195. {
  196.   Tool * tool;
  197.   Levels * private;
  198.  
  199.   /*  The tool options  */
  200.   if (! levels_options)
  201.     {
  202.       levels_options = tool_options_new (_("Levels"));
  203.       tools_register (LEVELS, levels_options);
  204.     }
  205.  
  206.   tool = tools_new_tool (LEVELS);
  207.   private = g_new0 (Levels, 1);
  208.  
  209.   tool->scroll_lock = TRUE;   /*  Disallow scrolling  */
  210.   tool->preserve    = FALSE;  /*  Don't preserve on drawable change  */
  211.  
  212.   tool->private = (void *) private;
  213.  
  214.   tool->control_func = levels_control;
  215.  
  216.   return tool;
  217. }
  218.  
  219. void
  220. levels_dialog_hide (void)
  221. {
  222.   if (levels_dialog)
  223.     levels_cancel_callback (NULL, (gpointer) levels_dialog);
  224. }
  225.  
  226. void
  227. tools_free_levels (Tool *tool)
  228. {
  229.   Levels * private;
  230.  
  231.   private = (Levels *) tool->private;
  232.  
  233.   /*  Close the color select dialog  */
  234.   levels_dialog_hide ();
  235.  
  236.   g_free (private);
  237. }
  238.  
  239. void
  240. levels_initialize (GDisplay *gdisp)
  241. {
  242.   gint i;
  243.  
  244.   if (gimp_image_is_empty (gdisp->gimage))
  245.     {
  246.       g_message (_("The image has no drawables."));
  247.       return;
  248.     }
  249.  
  250.   if (drawable_indexed (gimage_active_drawable (gdisp->gimage)))
  251.     {
  252.       g_message (_("Levels for indexed drawables cannot be adjusted."));
  253.       return;
  254.     }
  255.  
  256.   /*  The levels dialog  */
  257.   if (!levels_dialog)
  258.     levels_dialog = levels_dialog_new ();
  259.   else
  260.     if (!GTK_WIDGET_VISIBLE (levels_dialog->shell))
  261.       gtk_widget_show (levels_dialog->shell);
  262.  
  263.   /*  Initialize the values  */
  264.   levels_dialog->channel = GIMP_HISTOGRAM_VALUE;
  265.   for (i = 0; i < 5; i++)
  266.     {
  267.       levels_dialog->low_input[i]   = 0;
  268.       levels_dialog->gamma[i]       = 1.0;
  269.       levels_dialog->high_input[i]  = 255;
  270.       levels_dialog->low_output[i]  = 0;
  271.       levels_dialog->high_output[i] = 255;
  272.     }
  273.  
  274.   levels_dialog->drawable  = gimage_active_drawable (gdisp->gimage);
  275.   levels_dialog->color     = drawable_color (levels_dialog->drawable);
  276.   levels_dialog->image_map = image_map_create (gdisp, levels_dialog->drawable);
  277.  
  278.   /* check for alpha channel */
  279.   gtk_widget_set_sensitive (color_option_items[4],
  280.                 drawable_has_alpha (levels_dialog->drawable));
  281.   
  282.   /*  hide or show the channel menu based on image type  */
  283.   if (levels_dialog->color)
  284.     for (i = 0; i < 4; i++) 
  285.        gtk_widget_set_sensitive (color_option_items[i], TRUE);
  286.   else 
  287.     for (i = 1; i < 4; i++) 
  288.        gtk_widget_set_sensitive (color_option_items[i], FALSE);
  289.  
  290.   /* set the current selection */
  291.   gtk_option_menu_set_history (GTK_OPTION_MENU (levels_dialog->channel_menu),
  292.                    levels_dialog->channel);
  293.  
  294.  
  295.   levels_update (levels_dialog, LOW_INPUT | GAMMA | HIGH_INPUT | LOW_OUTPUT | HIGH_OUTPUT | DRAW);
  296.   levels_update (levels_dialog, INPUT_LEVELS | OUTPUT_LEVELS);
  297.  
  298.   gimp_histogram_calculate_drawable (levels_dialog->hist,
  299.                      levels_dialog->drawable);
  300.   histogram_widget_update (levels_dialog->histogram, levels_dialog->hist);
  301.   histogram_widget_range (levels_dialog->histogram, -1, -1);
  302.  
  303.   /* Merge-related undo release signal */
  304.  
  305.   levels_dialog->conn_id =
  306.     gtk_signal_connect (
  307.             GTK_OBJECT (gdisp->gimage), "layer_merge",
  308.             GTK_SIGNAL_FUNC (levels_cancel_callback),
  309.             levels_dialog
  310.                );
  311.  
  312. }
  313.  
  314. void
  315. levels_free (void)
  316. {
  317.   if (levels_dialog)
  318.     {
  319.       if (levels_dialog->image_map)
  320.     {
  321.       active_tool->preserve = TRUE;
  322.       image_map_abort (levels_dialog->image_map);
  323.       active_tool->preserve = FALSE;
  324.  
  325.       levels_dialog->image_map = NULL;
  326.  
  327.       if (levels_dialog->conn_id != 0)
  328.         {
  329.           gtk_signal_disconnect (GTK_OBJECT (gimp_drawable_gimage (levels_dialog->drawable)),
  330.                      levels_dialog->conn_id);
  331.           levels_dialog->conn_id = 0;
  332.         }
  333.     }
  334.       gtk_widget_destroy (levels_dialog->shell);
  335.     }
  336. }
  337.  
  338. /*******************/
  339. /*  Levels dialog  */
  340. /*******************/
  341.  
  342. static LevelsDialog *
  343. levels_dialog_new (void)
  344. {
  345.   LevelsDialog *ld;
  346.   GtkWidget *main_vbox;
  347.   GtkWidget *vbox;
  348.   GtkWidget *hbox;
  349.   GtkWidget *vbox2;
  350.   GtkWidget *label;
  351.   GtkWidget *frame;
  352.   GtkWidget *toggle;
  353.   GtkWidget *channel_hbox;
  354.   GtkWidget *hbbox;
  355.   GtkWidget *button;
  356.   GtkWidget *spinbutton;
  357.   GtkObject *data;
  358.  
  359.   ld = g_new0 (LevelsDialog, 1);
  360.   ld->channel = GIMP_HISTOGRAM_VALUE;
  361.   ld->preview = TRUE;
  362.   ld->lut     = gimp_lut_new ();
  363.   ld->hist    = gimp_histogram_new ();
  364.  
  365.   /*  The shell and main vbox  */
  366.   ld->shell = gimp_dialog_new (_("Levels"), "levels",
  367.                    tools_help_func, tool_info[LEVELS].private_tip,
  368.                    GTK_WIN_POS_NONE,
  369.                    FALSE, TRUE, FALSE,
  370.  
  371.                    _("OK"), levels_ok_callback,
  372.                    ld, NULL, NULL, TRUE, FALSE,
  373.                    _("Reset"), levels_reset_callback,
  374.                    ld, NULL, NULL, FALSE, FALSE,
  375.                    _("Cancel"), levels_cancel_callback,
  376.                    ld, NULL, NULL, FALSE, TRUE,
  377.  
  378.                    NULL);
  379.  
  380.   main_vbox = gtk_vbox_new (FALSE, 4);
  381.   gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 4);
  382.   gtk_container_add (GTK_CONTAINER (GTK_DIALOG (ld->shell)->vbox), main_vbox);
  383.  
  384.   hbox = gtk_hbox_new (TRUE, 0);
  385.   gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0);
  386.   gtk_widget_show (hbox);
  387.  
  388.   vbox = gtk_vbox_new (FALSE, 4);
  389.   gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
  390.  
  391.   /*  The option menu for selecting channels  */
  392.   channel_hbox = gtk_hbox_new (FALSE, 4);
  393.   gtk_box_pack_start (GTK_BOX (vbox), channel_hbox, FALSE, FALSE, 0);
  394.  
  395.   label = gtk_label_new (_("Modify Levels for Channel:"));
  396.   gtk_box_pack_start (GTK_BOX (channel_hbox), label, FALSE, FALSE, 0);
  397.   gtk_widget_show (label);
  398.  
  399.   ld->channel_menu = gimp_option_menu_new2
  400.     (FALSE, levels_channel_callback,
  401.      ld, GINT_TO_POINTER (ld->channel),
  402.  
  403.      _("Value"), GINT_TO_POINTER (GIMP_HISTOGRAM_VALUE), &color_option_items[0],
  404.      _("Red"),   GINT_TO_POINTER (GIMP_HISTOGRAM_RED),   &color_option_items[1],
  405.      _("Green"), GINT_TO_POINTER (GIMP_HISTOGRAM_GREEN), &color_option_items[2],
  406.      _("Blue"),  GINT_TO_POINTER (GIMP_HISTOGRAM_BLUE),  &color_option_items[3],
  407.      _("Alpha"), GINT_TO_POINTER (GIMP_HISTOGRAM_ALPHA), &color_option_items[4],
  408.  
  409.      NULL);
  410.   gtk_box_pack_start (GTK_BOX (channel_hbox), ld->channel_menu, FALSE, FALSE, 0);
  411.   gtk_widget_show (ld->channel_menu);
  412.  
  413.   gtk_widget_show (channel_hbox);
  414.  
  415.   /*  Horizontal box for input levels spinbuttons  */
  416.   hbox = gtk_hbox_new (FALSE, 4);
  417.   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
  418.  
  419.   label = gtk_label_new (_("Input Levels:"));
  420.   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
  421.   gtk_widget_show (label);
  422.  
  423.   /*  low input spin  */
  424.   data = gtk_adjustment_new (0, 0, 255, 1, 10, 10);
  425.   ld->low_input_data = GTK_ADJUSTMENT (data);
  426.  
  427.   spinbutton = gtk_spin_button_new (ld->low_input_data, 0.5, 0);
  428.   gtk_widget_set_usize (spinbutton, 50, -1);
  429.   gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE);
  430.   gtk_box_pack_start (GTK_BOX (hbox), spinbutton, FALSE, FALSE, 0);
  431.  
  432.   gtk_signal_connect (GTK_OBJECT (ld->low_input_data), "value_changed",
  433.                       GTK_SIGNAL_FUNC (levels_low_input_adjustment_update),
  434.                       ld);
  435.  
  436.   gtk_widget_show (spinbutton);
  437.  
  438.   /*  input gamma spin  */
  439.   data = gtk_adjustment_new (1, 0.1, 10, 0.1, 1, 1);
  440.   ld->gamma_data = GTK_ADJUSTMENT (data);
  441.  
  442.   spinbutton = gtk_spin_button_new (ld->gamma_data, 0.5, 2);
  443.   gtk_widget_set_usize (spinbutton, 50, -1);
  444.   gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE);
  445.   gtk_box_pack_start (GTK_BOX (hbox), spinbutton, FALSE, FALSE, 0);
  446.  
  447.   gtk_signal_connect (GTK_OBJECT (ld->gamma_data), "value_changed",
  448.               GTK_SIGNAL_FUNC (levels_gamma_adjustment_update),
  449.               ld);
  450.  
  451.   gtk_widget_show (spinbutton);
  452.  
  453.   /*  high input spin  */
  454.   data = gtk_adjustment_new (255, 0, 255, 1, 10, 10);
  455.   ld->high_input_data = GTK_ADJUSTMENT (data);
  456.  
  457.   spinbutton = gtk_spin_button_new (ld->high_input_data, 0.5, 0);
  458.   gtk_widget_set_usize (spinbutton, 50, -1);
  459.   gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE);
  460.   gtk_box_pack_start (GTK_BOX (hbox), spinbutton, FALSE, FALSE, 0);
  461.  
  462.   gtk_signal_connect (GTK_OBJECT (ld->high_input_data), "value_changed",
  463.               GTK_SIGNAL_FUNC (levels_high_input_adjustment_update),
  464.               ld);
  465.  
  466.   gtk_widget_show (spinbutton);
  467.   gtk_widget_show (hbox);
  468.  
  469.   /*  The levels histogram  */
  470.   hbox = gtk_hbox_new (TRUE, 2);
  471.   gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, FALSE, 0);
  472.  
  473.   frame = gtk_frame_new (NULL);
  474.   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
  475.   gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, FALSE, 0);
  476.   ld->histogram = histogram_widget_new (HISTOGRAM_WIDTH, HISTOGRAM_HEIGHT);
  477.   gtk_container_add (GTK_CONTAINER (frame), GTK_WIDGET (ld->histogram));
  478.  
  479.   /* ignore button_events, since we don't want the user to be able to set the range */
  480.   gtk_widget_set_events (GTK_WIDGET (ld->histogram), 
  481.              (GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK));
  482.  
  483.   gtk_widget_show (GTK_WIDGET (ld->histogram));
  484.   gtk_widget_show (frame);
  485.   gtk_widget_show (hbox);
  486.  
  487.   /*  The input levels drawing area  */
  488.   hbox = gtk_hbox_new (TRUE, 2);
  489.   gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, FALSE, 0);
  490.  
  491.   frame = gtk_frame_new (NULL);
  492.   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
  493.   gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, FALSE, 0);
  494.  
  495.   vbox2 = gtk_vbox_new (FALSE, 2);
  496.   gtk_container_add (GTK_CONTAINER (frame), vbox2);
  497.  
  498.   ld->input_levels_da[0] = gtk_preview_new (GTK_PREVIEW_COLOR);
  499.   gtk_preview_size (GTK_PREVIEW (ld->input_levels_da[0]),
  500.             DA_WIDTH, GRADIENT_HEIGHT);
  501.   gtk_widget_set_events (ld->input_levels_da[0], LEVELS_DA_MASK);
  502.   gtk_box_pack_start (GTK_BOX (vbox2), ld->input_levels_da[0], FALSE, TRUE, 0);
  503.  
  504.   gtk_signal_connect (GTK_OBJECT (ld->input_levels_da[0]), "event",
  505.               GTK_SIGNAL_FUNC (levels_input_da_events),
  506.               ld);
  507.  
  508.   ld->input_levels_da[1] = gtk_drawing_area_new ();
  509.   gtk_drawing_area_size (GTK_DRAWING_AREA (ld->input_levels_da[1]),
  510.              DA_WIDTH, CONTROL_HEIGHT);
  511.   gtk_widget_set_events (ld->input_levels_da[1], LEVELS_DA_MASK);
  512.   gtk_box_pack_start (GTK_BOX (vbox2), ld->input_levels_da[1], FALSE, TRUE, 0);
  513.  
  514.   gtk_signal_connect (GTK_OBJECT (ld->input_levels_da[1]), "event",
  515.               GTK_SIGNAL_FUNC (levels_input_da_events),
  516.               ld);
  517.  
  518.   gtk_widget_show (ld->input_levels_da[0]);
  519.   gtk_widget_show (ld->input_levels_da[1]);
  520.   gtk_widget_show (vbox2);
  521.   gtk_widget_show (frame);
  522.   gtk_widget_show (hbox);
  523.  
  524.   /*  Horizontal box for levels spin widgets  */
  525.   hbox = gtk_hbox_new (FALSE, 4);
  526.   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
  527.  
  528.   label = gtk_label_new (_("Output Levels:"));
  529.   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
  530.   gtk_widget_show (label);
  531.  
  532.   /*  low output spin  */
  533.   data = gtk_adjustment_new (0, 0, 255, 1, 10, 10);
  534.   ld->low_output_data = GTK_ADJUSTMENT (data);
  535.  
  536.   spinbutton = gtk_spin_button_new (ld->low_output_data, 0.5, 0);
  537.   gtk_widget_set_usize (spinbutton, 50, -1);
  538.   gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE);
  539.   gtk_box_pack_start (GTK_BOX (hbox), spinbutton, FALSE, FALSE, 0);
  540.  
  541.   gtk_signal_connect (GTK_OBJECT (ld->low_output_data), "value_changed",
  542.                       GTK_SIGNAL_FUNC (levels_low_output_adjustment_update),
  543.                       ld);
  544.  
  545.   gtk_widget_show (spinbutton);
  546.  
  547.   /*  high output spin  */
  548.   data = gtk_adjustment_new (255, 0, 255, 1, 10, 10);
  549.   ld->high_output_data = GTK_ADJUSTMENT (data);
  550.  
  551.   spinbutton = gtk_spin_button_new (ld->high_output_data, 0.5, 0);
  552.   gtk_widget_set_usize (spinbutton, 50, -1);
  553.   gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE);
  554.   gtk_box_pack_start (GTK_BOX (hbox), spinbutton, FALSE, FALSE, 0);
  555.  
  556.   gtk_signal_connect (GTK_OBJECT (ld->high_output_data), "value_changed",
  557.                       GTK_SIGNAL_FUNC (levels_high_output_adjustment_update),
  558.                       ld);
  559.  
  560.   gtk_widget_show (spinbutton);
  561.   gtk_widget_show (hbox);
  562.  
  563.   /*  The output levels drawing area  */
  564.   hbox = gtk_hbox_new (TRUE, 2);
  565.   gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, FALSE, 0);
  566.  
  567.   frame = gtk_frame_new (NULL);
  568.   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
  569.   gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, FALSE, 0);
  570.  
  571.   vbox2 = gtk_vbox_new (FALSE, 2);
  572.   gtk_container_add (GTK_CONTAINER (frame), vbox2);
  573.  
  574.   ld->output_levels_da[0] = gtk_preview_new (GTK_PREVIEW_COLOR);
  575.   gtk_preview_size (GTK_PREVIEW (ld->output_levels_da[0]), DA_WIDTH, GRADIENT_HEIGHT);
  576.   gtk_widget_set_events (ld->output_levels_da[0], LEVELS_DA_MASK);
  577.   gtk_box_pack_start (GTK_BOX (vbox2), ld->output_levels_da[0], FALSE, TRUE, 0);
  578.  
  579.   gtk_signal_connect (GTK_OBJECT (ld->output_levels_da[0]), "event",
  580.               GTK_SIGNAL_FUNC (levels_output_da_events),
  581.               ld);
  582.  
  583.   ld->output_levels_da[1] = gtk_preview_new (GTK_PREVIEW_GRAYSCALE);
  584.   gtk_preview_size (GTK_PREVIEW (ld->output_levels_da[1]), DA_WIDTH, CONTROL_HEIGHT);
  585.   gtk_widget_set_events (ld->output_levels_da[1], LEVELS_DA_MASK);
  586.   gtk_box_pack_start (GTK_BOX (vbox2), ld->output_levels_da[1], FALSE, TRUE, 0);
  587.  
  588.   gtk_signal_connect (GTK_OBJECT (ld->output_levels_da[1]), "event",
  589.               GTK_SIGNAL_FUNC (levels_output_da_events),
  590.               ld);
  591.  
  592.   gtk_widget_show (ld->output_levels_da[0]);
  593.   gtk_widget_show (ld->output_levels_da[1]);
  594.   gtk_widget_show (vbox2);
  595.   gtk_widget_show (frame);
  596.   gtk_widget_show (hbox);
  597.  
  598.   gtk_widget_show (vbox);
  599.  
  600.   /*  The preview toggle  */
  601.   hbox = gtk_hbox_new (FALSE, 4);
  602.   gtk_box_pack_end (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0);
  603.  
  604.   toggle = gtk_check_button_new_with_label (_("Preview"));
  605.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), ld->preview);
  606.   gtk_box_pack_end (GTK_BOX (hbox), toggle, FALSE, FALSE, 0);
  607.  
  608.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  609.               GTK_SIGNAL_FUNC (levels_preview_update),
  610.               ld);
  611.  
  612.   gtk_widget_show (toggle);
  613.  
  614.   gtk_widget_show (hbox);
  615.  
  616.   /*  Horizontal button box for auto / load / save  */
  617.   hbbox = gtk_hbutton_box_new ();
  618.   gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbbox), 4);
  619.   gtk_button_box_set_layout (GTK_BUTTON_BOX (hbbox), GTK_BUTTONBOX_SPREAD);
  620.   gtk_box_pack_end (GTK_BOX (main_vbox), hbbox, FALSE, FALSE, 0);
  621.  
  622.   button = gtk_button_new_with_label (_("Auto"));
  623.   GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
  624.   gtk_box_pack_start (GTK_BOX (hbbox), button, FALSE, FALSE, 0);
  625.  
  626.   gtk_signal_connect (GTK_OBJECT (button), "clicked",
  627.               GTK_SIGNAL_FUNC (levels_auto_callback),
  628.               ld);
  629.  
  630.   gtk_widget_show (button);
  631.  
  632.   button = gtk_button_new_with_label (_("Load"));
  633.   GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
  634.   gtk_box_pack_start (GTK_BOX (hbbox), button, FALSE, FALSE, 0);
  635.  
  636.   gtk_signal_connect (GTK_OBJECT (button), "clicked",
  637.               GTK_SIGNAL_FUNC (levels_load_callback),
  638.               ld->shell);
  639.  
  640.   gtk_widget_show (button);
  641.  
  642.   button = gtk_button_new_with_label (_("Save"));
  643.   GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
  644.   gtk_box_pack_start (GTK_BOX (hbbox), button, FALSE, FALSE, 0);
  645.  
  646.   gtk_signal_connect (GTK_OBJECT (button), "clicked",
  647.               GTK_SIGNAL_FUNC (levels_save_callback),
  648.               ld->shell);
  649.  
  650.   gtk_widget_show (button);
  651.  
  652.   gtk_widget_show (hbbox);
  653.  
  654.   gtk_widget_show (main_vbox);
  655.   gtk_widget_show (ld->shell);
  656.  
  657.   return ld;
  658. }
  659.  
  660. static void
  661. levels_draw_slider (GdkWindow *window,
  662.             GdkGC     *border_gc,
  663.             GdkGC     *fill_gc,
  664.             gint       xpos)
  665. {
  666.   int y;
  667.  
  668.   for (y = 0; y < CONTROL_HEIGHT; y++)
  669.     gdk_draw_line(window, fill_gc, xpos - y / 2, y,
  670.           xpos + y / 2, y);
  671.  
  672.   gdk_draw_line (window, border_gc, xpos, 0,
  673.          xpos - (CONTROL_HEIGHT - 1) / 2,  CONTROL_HEIGHT - 1);
  674.  
  675.   gdk_draw_line (window, border_gc, xpos, 0,
  676.          xpos + (CONTROL_HEIGHT - 1) / 2, CONTROL_HEIGHT - 1);
  677.  
  678.   gdk_draw_line (window, border_gc, xpos - (CONTROL_HEIGHT - 1) / 2, CONTROL_HEIGHT - 1,
  679.          xpos + (CONTROL_HEIGHT - 1) / 2, CONTROL_HEIGHT - 1);
  680. }
  681.  
  682. static void
  683. levels_erase_slider (GdkWindow *window,
  684.              gint       xpos)
  685. {
  686.   gdk_window_clear_area (window, xpos - (CONTROL_HEIGHT - 1) / 2, 0,
  687.              CONTROL_HEIGHT - 1, CONTROL_HEIGHT);
  688. }
  689.  
  690. static void
  691. levels_calculate_transfers (LevelsDialog *ld)
  692. {
  693.   gdouble inten;
  694.   gint i, j;
  695.  
  696.   /*  Recalculate the levels arrays  */
  697.   for (j = 0; j < 5; j++)
  698.     {
  699.       for (i = 0; i < 256; i++)
  700.     {
  701.       /*  determine input intensity  */
  702.       if (ld->high_input[j] != ld->low_input[j])
  703.         inten = (double) (i - ld->low_input[j]) /
  704.           (double) (ld->high_input[j] - ld->low_input[j]);
  705.       else
  706.         inten = (double) (i - ld->low_input[j]);
  707.  
  708.       inten = CLAMP (inten, 0.0, 1.0);
  709.       if (ld->gamma[j] != 0.0)
  710.         inten = pow (inten, (1.0 / ld->gamma[j]));
  711.       ld->input[j][i] = (unsigned char) (inten * 255.0 + 0.5);
  712.     }
  713.     }
  714. }
  715.  
  716. static void
  717. levels_update (LevelsDialog *ld,
  718.            gint          update)
  719. {
  720.   gint i;
  721.   gint   sel_channel;
  722.   
  723.   if(ld->color)
  724.     {
  725.       sel_channel = ld->channel;
  726.     }
  727.   else
  728.     {
  729.       if(ld->channel == 2)
  730.     sel_channel = GIMP_HISTOGRAM_ALPHA;
  731.       else
  732.     sel_channel = GIMP_HISTOGRAM_VALUE;
  733.     }
  734.  
  735.   /*  Recalculate the transfer arrays  */
  736.   levels_calculate_transfers (ld);
  737.   /* set up the lut */
  738.   levels_lut_setup (ld->lut, ld->gamma, ld->low_input, ld->high_input,
  739.             ld->low_output, ld->high_output,
  740.             gimp_drawable_bytes(ld->drawable));
  741.  
  742.   if (update & LOW_INPUT)
  743.     {
  744.       gtk_adjustment_set_value (ld->low_input_data,
  745.                 ld->low_input[ld->channel]);
  746.     }
  747.   if (update & GAMMA)
  748.     {
  749.       gtk_adjustment_set_value (ld->gamma_data,
  750.                 ld->gamma[ld->channel]);
  751.     }
  752.   if (update & HIGH_INPUT)
  753.     {
  754.       gtk_adjustment_set_value (ld->high_input_data,
  755.                 ld->high_input[ld->channel]);
  756.     }
  757.   if (update & LOW_OUTPUT)
  758.     {
  759.       gtk_adjustment_set_value (ld->low_output_data,
  760.                 ld->low_output[ld->channel]);
  761.     }
  762.   if (update & HIGH_OUTPUT)
  763.     {
  764.       gtk_adjustment_set_value (ld->high_output_data,
  765.                 ld->high_output[ld->channel]);
  766.     }
  767.   if (update & INPUT_LEVELS)
  768.     {
  769.       guchar buf[DA_WIDTH*3];
  770.  
  771.       switch (sel_channel)
  772.     {
  773.     default:
  774.       g_warning ("unknown channel type, can't happen\n");
  775.       /* fall through */
  776.     case GIMP_HISTOGRAM_VALUE:
  777.     case GIMP_HISTOGRAM_ALPHA:
  778.       for (i = 0; i < DA_WIDTH; i++)
  779.         {
  780.           buf[3*i+0] = ld->input[sel_channel][i];
  781.           buf[3*i+1] = ld->input[sel_channel][i];
  782.           buf[3*i+2] = ld->input[sel_channel][i];
  783.         }
  784.       break;
  785.  
  786.     case GIMP_HISTOGRAM_RED:
  787.     case GIMP_HISTOGRAM_GREEN:
  788.     case GIMP_HISTOGRAM_BLUE:      
  789.       for (i = 0; i < DA_WIDTH; i++)
  790.         {
  791.           buf[3*i+0] = ld->input[GIMP_HISTOGRAM_RED][i];
  792.           buf[3*i+1] = ld->input[GIMP_HISTOGRAM_GREEN][i];
  793.           buf[3*i+2] = ld->input[GIMP_HISTOGRAM_BLUE][i];
  794.         }
  795.       break;
  796.     }
  797.  
  798.       for (i = 0; i < GRADIENT_HEIGHT/2; i++)
  799.     gtk_preview_draw_row (GTK_PREVIEW (ld->input_levels_da[0]),
  800.                   buf, 0, i, DA_WIDTH);
  801.  
  802.  
  803.       for (i = 0; i < DA_WIDTH; i++)
  804.     {
  805.       buf[3*i+0] = i;
  806.       buf[3*i+1] = i;
  807.       buf[3*i+2] = i;
  808.     }
  809.  
  810.       for (i = GRADIENT_HEIGHT/2; i < GRADIENT_HEIGHT; i++)
  811.     gtk_preview_draw_row (GTK_PREVIEW (ld->input_levels_da[0]),
  812.                   buf, 0, i, DA_WIDTH);
  813.  
  814.       if (update & DRAW)
  815.     gtk_widget_draw (ld->input_levels_da[0], NULL);
  816.     }
  817.   if (update & OUTPUT_LEVELS)
  818.     {
  819.       guchar buf[DA_WIDTH*3];
  820.       guchar r, g, b;
  821.  
  822.       r = g = b = 0;
  823.       switch (sel_channel)
  824.     {
  825.     default:
  826.       g_warning ("unknown channel type, can't happen\n");
  827.       /* fall through */
  828.     case GIMP_HISTOGRAM_VALUE:
  829.     case GIMP_HISTOGRAM_ALPHA:  r = g = b = 1; break;
  830.     case GIMP_HISTOGRAM_RED:    r = 1;         break;
  831.     case GIMP_HISTOGRAM_GREEN:  g = 1;         break;
  832.     case GIMP_HISTOGRAM_BLUE:   b = 1;         break;
  833.     }
  834.  
  835.       for (i = 0; i < DA_WIDTH; i++)
  836.     {
  837.       buf[3*i+0] = i*r;
  838.       buf[3*i+1] = i*g;
  839.       buf[3*i+2] = i*b;
  840.     }
  841.  
  842.       for (i = 0; i < GRADIENT_HEIGHT; i++)
  843.     gtk_preview_draw_row (GTK_PREVIEW (ld->output_levels_da[0]),
  844.                   buf, 0, i, DA_WIDTH);
  845.  
  846.       if (update & DRAW)
  847.     gtk_widget_draw (ld->output_levels_da[0], NULL);
  848.     }
  849.   if (update & INPUT_SLIDERS)
  850.     {
  851.       double width, mid, tmp;
  852.  
  853.       levels_erase_slider (ld->input_levels_da[1]->window, ld->slider_pos[0]);
  854.       levels_erase_slider (ld->input_levels_da[1]->window, ld->slider_pos[1]);
  855.       levels_erase_slider (ld->input_levels_da[1]->window, ld->slider_pos[2]);
  856.  
  857.       ld->slider_pos[0] = DA_WIDTH * ((double) ld->low_input[ld->channel] / 255.0);
  858.       ld->slider_pos[2] = DA_WIDTH * ((double) ld->high_input[ld->channel] / 255.0);
  859.  
  860.       width = (double) (ld->slider_pos[2] - ld->slider_pos[0]) / 2.0;
  861.       mid = ld->slider_pos[0] + width;
  862.       tmp = log10 (1.0 / ld->gamma[ld->channel]);
  863.       ld->slider_pos[1] = (int) (mid + width * tmp + 0.5);
  864.  
  865.       levels_draw_slider (ld->input_levels_da[1]->window,
  866.               ld->input_levels_da[1]->style->black_gc,
  867.               ld->input_levels_da[1]->style->dark_gc[GTK_STATE_NORMAL],
  868.               ld->slider_pos[1]);
  869.       levels_draw_slider (ld->input_levels_da[1]->window,
  870.               ld->input_levels_da[1]->style->black_gc,
  871.               ld->input_levels_da[1]->style->black_gc,
  872.               ld->slider_pos[0]);
  873.       levels_draw_slider (ld->input_levels_da[1]->window,
  874.               ld->input_levels_da[1]->style->black_gc,
  875.               ld->input_levels_da[1]->style->white_gc,
  876.               ld->slider_pos[2]);
  877.     }
  878.   if (update & OUTPUT_SLIDERS)
  879.     {
  880.       levels_erase_slider (ld->output_levels_da[1]->window, ld->slider_pos[3]);
  881.       levels_erase_slider (ld->output_levels_da[1]->window, ld->slider_pos[4]);
  882.  
  883.       ld->slider_pos[3] = DA_WIDTH * ((double) ld->low_output[ld->channel] / 255.0);
  884.       ld->slider_pos[4] = DA_WIDTH * ((double) ld->high_output[ld->channel] / 255.0);
  885.  
  886.       levels_draw_slider (ld->output_levels_da[1]->window,
  887.               ld->output_levels_da[1]->style->black_gc,
  888.               ld->output_levels_da[1]->style->black_gc,
  889.               ld->slider_pos[3]);
  890.       levels_draw_slider (ld->output_levels_da[1]->window,
  891.               ld->output_levels_da[1]->style->black_gc,
  892.               ld->output_levels_da[1]->style->white_gc,
  893.               ld->slider_pos[4]);
  894.     }
  895. }
  896.  
  897. static void
  898. levels_preview (LevelsDialog *ld)
  899. {
  900.   if (!ld->image_map)
  901.     {
  902.       g_warning ("levels_preview: No Image Map");
  903.       return;
  904.     }
  905.   if (!ld->preview)
  906.     return;
  907.   active_tool->preserve = TRUE;
  908.   image_map_apply (ld->image_map, (ImageMapApplyFunc) gimp_lut_process_2,
  909.            (void *) ld->lut);
  910.   active_tool->preserve = FALSE;
  911. }
  912.  
  913. static void
  914. levels_channel_callback (GtkWidget *widget,
  915.              gpointer   data)
  916. {
  917.   LevelsDialog *ld;
  918.  
  919.   ld = (LevelsDialog *) data;
  920.  
  921.   gimp_menu_item_update (widget, &ld->channel);
  922.  
  923.   if(ld->color)
  924.     histogram_widget_channel (ld->histogram, ld->channel);
  925.   else
  926.     {
  927.       if(ld->channel > 1) 
  928.     {
  929.       histogram_widget_channel (ld->histogram, 1);
  930.       ld->channel = 2;
  931.     }
  932.       else
  933.     {
  934.       histogram_widget_channel (ld->histogram, 0);
  935.       ld->channel = 1;
  936.     } 
  937.     }
  938.   levels_update (ld, ALL);
  939. }
  940.  
  941. static void
  942. levels_adjust_channel (LevelsDialog    *ld,
  943.                GimpHistogram   *hist,
  944.                gint             channel)
  945. {
  946.   gint i;
  947.   gdouble count, new_count, percentage, next_percentage;
  948.  
  949.   ld->gamma[channel]       = 1.0;
  950.   ld->low_output[channel]  = 0;
  951.   ld->high_output[channel] = 255;
  952.  
  953.   count = gimp_histogram_get_count (hist, 0, 255);
  954.  
  955.   if (count == 0.0)
  956.     {
  957.       ld->low_input[channel] = 0;
  958.       ld->high_input[channel] = 0;
  959.     }
  960.   else
  961.     {
  962.       /*  Set the low input  */
  963.       new_count = 0.0;
  964.       for (i = 0; i < 255; i++)
  965.     {
  966.       new_count += gimp_histogram_get_value(hist, channel, i);
  967.       percentage = new_count / count;
  968.       next_percentage =
  969.         (new_count + gimp_histogram_get_value (hist,
  970.                            channel,
  971.                            i + 1)) / count;
  972.       if (fabs (percentage - 0.006) < fabs (next_percentage - 0.006))
  973.         {
  974.           ld->low_input[channel] = i + 1;
  975.           break;
  976.         }
  977.     }
  978.       /*  Set the high input  */
  979.       new_count = 0.0;
  980.       for (i = 255; i > 0; i--)
  981.     {
  982.       new_count += gimp_histogram_get_value(hist, channel, i);
  983.       percentage = new_count / count;
  984.       next_percentage =
  985.         (new_count + gimp_histogram_get_value (hist,
  986.                            channel,
  987.                            i - 1)) / count;
  988.       if (fabs (percentage - 0.006) < fabs (next_percentage - 0.006))
  989.         {
  990.           ld->high_input[channel] = i - 1;
  991.           break;
  992.         }
  993.     }
  994.     }
  995. }
  996.  
  997. static void
  998. levels_reset_callback (GtkWidget *widget,
  999.                gpointer   data)
  1000. {
  1001.   LevelsDialog *ld;
  1002.  
  1003.   ld = (LevelsDialog *) data;
  1004.  
  1005.   ld->low_input[ld->channel]   = 0;
  1006.   ld->gamma[ld->channel]       = 1.0;
  1007.   ld->high_input[ld->channel]  = 255;
  1008.   ld->low_output[ld->channel]  = 0;
  1009.   ld->high_output[ld->channel] = 255;
  1010.  
  1011.   levels_update (ld, ALL);
  1012.  
  1013.   if (ld->preview)
  1014.     levels_preview (ld);
  1015. }
  1016.  
  1017. static void
  1018. levels_ok_callback (GtkWidget *widget,
  1019.             gpointer   data)
  1020. {
  1021.   LevelsDialog *ld;
  1022.  
  1023.   ld = (LevelsDialog *) data;
  1024.  
  1025.   gimp_dialog_hide (ld->shell);
  1026.  
  1027.   active_tool->preserve = TRUE;
  1028.  
  1029.   if (!ld->preview)
  1030.     {
  1031.       levels_lut_setup (ld->lut, ld->gamma, ld->low_input, ld->high_input,
  1032.             ld->low_output, ld->high_output,
  1033.             gimp_drawable_bytes (ld->drawable));
  1034.       image_map_apply (ld->image_map, (ImageMapApplyFunc) gimp_lut_process_2,
  1035.                (void *) ld->lut);
  1036.     }
  1037.  
  1038.   if (ld->image_map)
  1039.     image_map_commit (ld->image_map);
  1040.  
  1041.   active_tool->preserve = FALSE;
  1042.  
  1043.   ld->image_map = NULL;
  1044.  
  1045.   active_tool->gdisp_ptr = NULL;
  1046.   active_tool->drawable = NULL;
  1047. }
  1048.  
  1049. static void
  1050. levels_cancel_callback (GtkWidget *widget,
  1051.             gpointer   data)
  1052. {
  1053.   LevelsDialog *ld;
  1054.  
  1055.   ld = (LevelsDialog *) data;
  1056.  
  1057.   gimp_dialog_hide (ld->shell);
  1058.  
  1059.   if (ld->image_map)
  1060.     {
  1061.       active_tool->preserve = TRUE;
  1062.       image_map_abort (ld->image_map);
  1063.       active_tool->preserve = FALSE;
  1064.  
  1065.       gdisplays_flush ();
  1066.       ld->image_map = NULL;
  1067.     }
  1068.  
  1069.   if (ld->conn_id != 0)
  1070.     {
  1071.       gtk_signal_disconnect (
  1072.                  GTK_OBJECT (gimp_drawable_gimage (ld->drawable)), 
  1073.                  ld->conn_id
  1074.                 );
  1075.       ld->conn_id = 0;
  1076.     }
  1077.  
  1078.   active_tool->gdisp_ptr = NULL;
  1079.   active_tool->drawable = NULL;
  1080. }
  1081.  
  1082. static void
  1083. levels_auto_callback (GtkWidget *widget,
  1084.               gpointer   data)
  1085. {
  1086.   LevelsDialog *ld;
  1087.   int channel;
  1088.  
  1089.   ld = (LevelsDialog *) data;
  1090.  
  1091.   if (ld->color)
  1092.     {
  1093.       /*  Set the overall value to defaults  */
  1094.       ld->low_input[GIMP_HISTOGRAM_VALUE]   = 0;
  1095.       ld->gamma[GIMP_HISTOGRAM_VALUE]       = 1.0;
  1096.       ld->high_input[GIMP_HISTOGRAM_VALUE]  = 255;
  1097.       ld->low_output[GIMP_HISTOGRAM_VALUE]  = 0;
  1098.       ld->high_output[GIMP_HISTOGRAM_VALUE] = 255;
  1099.  
  1100.       for (channel = 0; channel < 3; channel ++)
  1101.     levels_adjust_channel (ld, ld->hist, channel + 1);
  1102.     }
  1103.   else
  1104.     levels_adjust_channel (ld, ld->hist, GIMP_HISTOGRAM_VALUE);
  1105.  
  1106.   levels_update (ld, ALL);
  1107.   if (ld->preview)
  1108.     levels_preview (ld);
  1109. }
  1110.  
  1111. static void
  1112. levels_load_callback (GtkWidget *widget,
  1113.               gpointer   data)
  1114. {
  1115.   if (!file_dlg)
  1116.     file_dialog_create (GTK_WIDGET (data));
  1117.   else if (GTK_WIDGET_VISIBLE (file_dlg)) 
  1118.     return;
  1119.  
  1120.   load_save = TRUE;
  1121.  
  1122.   gtk_window_set_title (GTK_WINDOW (file_dlg), _("Load Levels"));
  1123.   gtk_widget_show (file_dlg);
  1124. }
  1125.  
  1126. static void
  1127. levels_save_callback (GtkWidget *widget,
  1128.               gpointer   data)
  1129. {
  1130.   if (!file_dlg)
  1131.     file_dialog_create (GTK_WIDGET (data));
  1132.   else if (GTK_WIDGET_VISIBLE (file_dlg)) 
  1133.     return;
  1134.  
  1135.   load_save = FALSE;
  1136.  
  1137.   gtk_window_set_title (GTK_WINDOW (file_dlg), _("Save Levels"));
  1138.   gtk_widget_show (file_dlg);
  1139. }
  1140.  
  1141. static void
  1142. levels_preview_update (GtkWidget *widget,
  1143.                gpointer   data)
  1144. {
  1145.   LevelsDialog *ld;
  1146.  
  1147.   ld = (LevelsDialog *) data;
  1148.  
  1149.   if (GTK_TOGGLE_BUTTON (widget)->active)
  1150.     {
  1151.       ld->preview = TRUE;
  1152.       levels_preview (ld);
  1153.     }
  1154.   else
  1155.     {
  1156.       ld->preview = FALSE;
  1157.       if (ld->image_map)
  1158.     {
  1159.       active_tool->preserve = TRUE;
  1160.       image_map_clear (ld->image_map);
  1161.       active_tool->preserve = FALSE;
  1162.       gdisplays_flush ();
  1163.     }
  1164.     }
  1165.  
  1166. }
  1167.  
  1168. static void
  1169. levels_low_input_adjustment_update (GtkAdjustment *adjustment,
  1170.                     gpointer       data)
  1171. {
  1172.   LevelsDialog *ld;
  1173.   gint value;
  1174.  
  1175.   ld = (LevelsDialog *) data;
  1176.  
  1177.   value = (gint) (adjustment->value + 0.5);
  1178.   value = CLAMP (value, 0, ld->high_input[ld->channel]);
  1179.  
  1180.   /*  enforce a consistent displayed value (low_input <= high_input)  */
  1181.   gtk_adjustment_set_value (adjustment, value);
  1182.  
  1183.   if (ld->low_input[ld->channel] != value)
  1184.     {
  1185.       ld->low_input[ld->channel] = value;
  1186.       levels_update (ld, INPUT_LEVELS | INPUT_SLIDERS | DRAW);
  1187.  
  1188.       if (ld->preview)
  1189.     levels_preview (ld);
  1190.     }
  1191. }
  1192.  
  1193. static void
  1194. levels_gamma_adjustment_update (GtkAdjustment *adjustment,
  1195.                 gpointer       data)
  1196. {
  1197.   LevelsDialog *ld;
  1198.  
  1199.   ld = (LevelsDialog *) data;
  1200.  
  1201.   if (ld->gamma[ld->channel] != adjustment->value)
  1202.     {
  1203.       ld->gamma[ld->channel] = adjustment->value;
  1204.       levels_update (ld, INPUT_LEVELS | INPUT_SLIDERS | DRAW);
  1205.  
  1206.       if (ld->preview)
  1207.     levels_preview (ld);
  1208.     }
  1209. }
  1210.  
  1211. static void
  1212. levels_high_input_adjustment_update (GtkAdjustment *adjustment,
  1213.                      gpointer       data)
  1214. {
  1215.   LevelsDialog *ld;
  1216.   gint value;
  1217.  
  1218.   ld = (LevelsDialog *) data;
  1219.  
  1220.   value = (gint) (adjustment->value + 0.5);
  1221.   value = CLAMP (value, ld->low_input[ld->channel], 255);
  1222.  
  1223.   /*  enforce a consistent displayed value (high_input >= low_input)  */
  1224.   gtk_adjustment_set_value (adjustment, value);
  1225.  
  1226.   if (ld->high_input[ld->channel] != value)
  1227.     {
  1228.       ld->high_input[ld->channel] = value;
  1229.       levels_update (ld, INPUT_LEVELS | INPUT_SLIDERS | DRAW);
  1230.  
  1231.       if (ld->preview)
  1232.     levels_preview (ld);
  1233.     }
  1234. }
  1235.  
  1236. static void
  1237. levels_low_output_adjustment_update (GtkAdjustment *adjustment,
  1238.                      gpointer       data)
  1239. {
  1240.   LevelsDialog *ld;
  1241.   gint value;
  1242.  
  1243.   ld = (LevelsDialog *) data;
  1244.  
  1245.   value = (gint) (adjustment->value + 0.5);
  1246.  
  1247.   if (ld->low_output[ld->channel] != value)
  1248.     {
  1249.       ld->low_output[ld->channel] = value;
  1250.       levels_update (ld, OUTPUT_LEVELS | OUTPUT_SLIDERS | DRAW);
  1251.  
  1252.       if (ld->preview)
  1253.     levels_preview (ld);
  1254.     }
  1255. }
  1256.  
  1257. static void
  1258. levels_high_output_adjustment_update (GtkAdjustment *adjustment,
  1259.                       gpointer       data)
  1260. {
  1261.   LevelsDialog *ld;
  1262.   gint value;
  1263.  
  1264.   ld = (LevelsDialog *) data;
  1265.  
  1266.   value = (gint) (adjustment->value + 0.5);
  1267.  
  1268.   if (ld->high_output[ld->channel] != value)
  1269.     {
  1270.       ld->high_output[ld->channel] = value;
  1271.       levels_update (ld, OUTPUT_LEVELS | OUTPUT_SLIDERS | DRAW);
  1272.  
  1273.       if (ld->preview)
  1274.     levels_preview (ld);
  1275.     }
  1276. }
  1277.  
  1278. static gint
  1279. levels_input_da_events (GtkWidget    *widget,
  1280.             GdkEvent     *event,
  1281.             LevelsDialog *ld)
  1282. {
  1283.   GdkEventButton *bevent;
  1284.   GdkEventMotion *mevent;
  1285.   gchar text[12];
  1286.   gdouble width, mid, tmp;
  1287.   gint x, distance;
  1288.   gint i;
  1289.   gint update = FALSE;
  1290.  
  1291.   switch (event->type)
  1292.     {
  1293.     case GDK_EXPOSE:
  1294.       if (widget == ld->input_levels_da[1])
  1295.     levels_update (ld, INPUT_SLIDERS);
  1296.       break;
  1297.  
  1298.     case GDK_BUTTON_PRESS:
  1299.       gtk_grab_add (widget);
  1300.       bevent = (GdkEventButton *) event;
  1301.  
  1302.       distance = G_MAXINT;
  1303.       for (i = 0; i < 3; i++)
  1304.     if (fabs (bevent->x - ld->slider_pos[i]) < distance)
  1305.       {
  1306.         ld->active_slider = i;
  1307.         distance = fabs (bevent->x - ld->slider_pos[i]);
  1308.       }
  1309.  
  1310.       x = bevent->x;
  1311.       update = TRUE;
  1312.       break;
  1313.  
  1314.     case GDK_BUTTON_RELEASE:
  1315.       gtk_grab_remove (widget);
  1316.       switch (ld->active_slider)
  1317.     {
  1318.     case 0:  /*  low input  */
  1319.       levels_update (ld, LOW_INPUT | GAMMA | DRAW);
  1320.       break;
  1321.     case 1:  /*  gamma  */
  1322.       levels_update (ld, GAMMA);
  1323.       break;
  1324.     case 2:  /*  high input  */
  1325.       levels_update (ld, HIGH_INPUT | GAMMA | DRAW);
  1326.       break;
  1327.     }
  1328.  
  1329.       if (ld->preview)
  1330.     levels_preview (ld);
  1331.       break;
  1332.  
  1333.     case GDK_MOTION_NOTIFY:
  1334.       mevent = (GdkEventMotion *) event;
  1335.       gdk_window_get_pointer (widget->window, &x, NULL, NULL);
  1336.       update = TRUE;
  1337.       break;
  1338.  
  1339.     default:
  1340.       break;
  1341.     }
  1342.  
  1343.   if (update)
  1344.     {
  1345.       switch (ld->active_slider)
  1346.     {
  1347.     case 0:  /*  low input  */
  1348.       ld->low_input[ld->channel] = ((double) x / (double) DA_WIDTH) * 255.0;
  1349.       ld->low_input[ld->channel] = CLAMP (ld->low_input[ld->channel], 0,
  1350.                           ld->high_input[ld->channel]);
  1351.       break;
  1352.  
  1353.     case 1:  /*  gamma  */
  1354.       width = (double) (ld->slider_pos[2] - ld->slider_pos[0]) / 2.0;
  1355.       mid = ld->slider_pos[0] + width;
  1356.  
  1357.       x = CLAMP (x, ld->slider_pos[0], ld->slider_pos[2]);
  1358.       tmp = (double) (x - mid) / width;
  1359.       ld->gamma[ld->channel] = 1.0 / pow (10, tmp);
  1360.  
  1361.       /*  round the gamma value to the nearest 1/100th  */
  1362.       g_snprintf (text, sizeof (text), "%2.2f", ld->gamma[ld->channel]);
  1363.       ld->gamma[ld->channel] = atof (text);
  1364.       break;
  1365.  
  1366.     case 2:  /*  high input  */
  1367.       ld->high_input[ld->channel] = ((double) x / (double) DA_WIDTH) * 255.0;
  1368.       ld->high_input[ld->channel] = CLAMP (ld->high_input[ld->channel],
  1369.                            ld->low_input[ld->channel], 255);
  1370.       break;
  1371.     }
  1372.  
  1373.       levels_update (ld, INPUT_SLIDERS | INPUT_LEVELS | DRAW);
  1374.     }
  1375.  
  1376.   return FALSE;
  1377. }
  1378.  
  1379. static gint
  1380. levels_output_da_events (GtkWidget    *widget,
  1381.              GdkEvent     *event,
  1382.              LevelsDialog *ld)
  1383. {
  1384.   GdkEventButton *bevent;
  1385.   GdkEventMotion *mevent;
  1386.   int x, distance;
  1387.   int i;
  1388.   int update = FALSE;
  1389.  
  1390.   switch (event->type)
  1391.     {
  1392.     case GDK_EXPOSE:
  1393.       if (widget == ld->output_levels_da[1])
  1394.     levels_update (ld, OUTPUT_SLIDERS);
  1395.       break;
  1396.  
  1397.  
  1398.     case GDK_BUTTON_PRESS:
  1399.       bevent = (GdkEventButton *) event;
  1400.  
  1401.       distance = G_MAXINT;
  1402.       for (i = 3; i < 5; i++)
  1403.     if (fabs (bevent->x - ld->slider_pos[i]) < distance)
  1404.       {
  1405.         ld->active_slider = i;
  1406.         distance = fabs (bevent->x - ld->slider_pos[i]);
  1407.       }
  1408.  
  1409.       x = bevent->x;
  1410.       update = TRUE;
  1411.       break;
  1412.  
  1413.     case GDK_BUTTON_RELEASE:
  1414.       switch (ld->active_slider)
  1415.     {
  1416.     case 3:  /*  low output  */
  1417.       levels_update (ld, LOW_OUTPUT | DRAW);
  1418.       break;
  1419.     case 4:  /*  high output  */
  1420.       levels_update (ld, HIGH_OUTPUT | DRAW);
  1421.       break;
  1422.     }
  1423.  
  1424.       if (ld->preview)
  1425.     levels_preview (ld);
  1426.       break;
  1427.  
  1428.     case GDK_MOTION_NOTIFY:
  1429.       mevent = (GdkEventMotion *) event;
  1430.       gdk_window_get_pointer (widget->window, &x, NULL, NULL);
  1431.       update = TRUE;
  1432.       break;
  1433.  
  1434.     default:
  1435.       break;
  1436.     }
  1437.  
  1438.   if (update)
  1439.     {
  1440.       switch (ld->active_slider)
  1441.     {
  1442.     case 3:  /*  low output  */
  1443.       ld->low_output[ld->channel] = ((double) x / (double) DA_WIDTH) * 255.0;
  1444.       ld->low_output[ld->channel] = CLAMP (ld->low_output[ld->channel],
  1445.                            0, 255);
  1446.       break;
  1447.  
  1448.     case 4:  /*  high output  */
  1449.       ld->high_output[ld->channel] = ((double) x / (double) DA_WIDTH) * 255.0;
  1450.       ld->high_output[ld->channel] = CLAMP (ld->high_output[ld->channel],
  1451.                         0, 255);
  1452.       break;
  1453.     }
  1454.  
  1455.       levels_update (ld, OUTPUT_SLIDERS | DRAW);
  1456.     }
  1457.  
  1458.   return FALSE;
  1459. }
  1460.  
  1461. static void
  1462. file_dialog_create (GtkWidget *parent)
  1463. {
  1464.   gchar *temp;
  1465.  
  1466.   file_dlg = gtk_file_selection_new (_("Load/Save Levels"));
  1467.   gtk_window_set_wmclass (GTK_WINDOW (file_dlg), "load_save_levels", "Gimp");
  1468.   gtk_window_set_position (GTK_WINDOW (file_dlg), GTK_WIN_POS_MOUSE);
  1469.  
  1470.   gtk_container_set_border_width (GTK_CONTAINER (file_dlg), 2);
  1471.   gtk_container_set_border_width (GTK_CONTAINER (GTK_FILE_SELECTION (file_dlg)->button_area), 2);
  1472.  
  1473.   gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (file_dlg)->cancel_button),
  1474.               "clicked", GTK_SIGNAL_FUNC (file_dialog_cancel_callback),
  1475.               NULL);
  1476.   gtk_signal_connect (GTK_OBJECT (file_dlg), "delete_event",
  1477.               GTK_SIGNAL_FUNC (file_dialog_cancel_callback),
  1478.               NULL);
  1479.   gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (file_dlg)->ok_button),
  1480.               "clicked", GTK_SIGNAL_FUNC (file_dialog_ok_callback),
  1481.               NULL);
  1482.  
  1483.   gtk_signal_connect (GTK_OBJECT (parent), "unmap",
  1484.               GTK_SIGNAL_FUNC (file_dialog_cancel_callback),
  1485.               NULL);
  1486.  
  1487.   temp = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "levels" G_DIR_SEPARATOR_S,
  1488.                     gimp_directory ());
  1489.   gtk_file_selection_set_filename (GTK_FILE_SELECTION (file_dlg), temp);
  1490.   g_free (temp);
  1491.  
  1492.   gimp_help_connect_help_accel (file_dlg, tools_help_func,
  1493.                 tool_info[LEVELS].private_tip);
  1494. }
  1495.  
  1496. static void
  1497. file_dialog_ok_callback (GtkWidget *widget,
  1498.              gpointer   data)
  1499. {
  1500.   FILE  *f;
  1501.   gchar *filename;
  1502.  
  1503.   filename = gtk_file_selection_get_filename (GTK_FILE_SELECTION (file_dlg));
  1504.  
  1505.   if (load_save)
  1506.     {
  1507.       f = fopen (filename, "rt");
  1508.  
  1509.       if (!f)
  1510.     {
  1511.       g_message (_("Unable to open file %s"), filename);
  1512.       return;
  1513.     }
  1514.  
  1515.       if (!levels_read_from_file (f))
  1516.     {
  1517.       g_message (("Error in reading file %s"), filename);
  1518.       return;
  1519.     }
  1520.  
  1521.       fclose (f);
  1522.     }
  1523.   else
  1524.     {
  1525.       f = fopen(filename, "wt");
  1526.  
  1527.       if (!f)
  1528.     {
  1529.       g_message (_("Unable to open file %s"), filename);
  1530.       return;
  1531.     }
  1532.  
  1533.       levels_write_to_file (f);
  1534.  
  1535.       fclose (f);
  1536.     }
  1537.   file_dialog_cancel_callback (file_dlg, NULL);
  1538. }
  1539.  
  1540. static void
  1541. file_dialog_cancel_callback (GtkWidget *widget,
  1542.                  gpointer   data)
  1543. {
  1544.   gimp_dialog_hide (file_dlg);
  1545. }
  1546.  
  1547. static gboolean
  1548. levels_read_from_file (FILE *f)
  1549. {
  1550.   int low_input[5];
  1551.   int high_input[5];
  1552.   int low_output[5];
  1553.   int high_output[5];
  1554.   double gamma[5];
  1555.   int i, fields;
  1556.   char buf[50], *nptr;
  1557.   
  1558.   if (!fgets (buf, 50, f))
  1559.     return FALSE;
  1560.  
  1561.   if (strcmp (buf, "# GIMP Levels File\n") != 0)
  1562.     return FALSE;
  1563.  
  1564.   for (i = 0; i < 5; i++)
  1565.     {
  1566.       fields = fscanf (f, "%d %d %d %d ",
  1567.                &low_input[i],
  1568.                &high_input[i],
  1569.                &low_output[i],
  1570.                &high_output[i]);
  1571.  
  1572.       if (fields != 4)
  1573.     return FALSE;
  1574.  
  1575.       if (!fgets (buf, 50, f))
  1576.     return FALSE;
  1577.  
  1578.       gamma[i] = strtod(buf, &nptr);
  1579.  
  1580.       if (buf == nptr || errno == ERANGE)
  1581.     return FALSE;
  1582.     }
  1583.  
  1584.   for (i = 0; i < 5; i++)
  1585.     {
  1586.       levels_dialog->low_input[i] = low_input[i];
  1587.       levels_dialog->high_input[i] = high_input[i];
  1588.       levels_dialog->low_output[i] = low_output[i];
  1589.       levels_dialog->high_output[i] = high_output[i];
  1590.       levels_dialog->gamma[i] = gamma[i];
  1591.     }
  1592.  
  1593.   levels_update (levels_dialog, ALL);
  1594.  
  1595.   if (levels_dialog->preview)
  1596.     levels_preview (levels_dialog);
  1597.  
  1598.   return TRUE;
  1599. }
  1600.  
  1601. static void
  1602. levels_write_to_file (FILE *f)
  1603. {
  1604.   int i;
  1605.  
  1606.   fprintf (f, "# GIMP Levels File\n");
  1607.  
  1608.   for (i = 0; i < 5; i++)
  1609.     {
  1610.       fprintf (f, "%d %d %d %d %f\n",
  1611.            levels_dialog->low_input[i],
  1612.            levels_dialog->high_input[i],
  1613.            levels_dialog->low_output[i],
  1614.            levels_dialog->high_output[i],
  1615.            levels_dialog->gamma[i]);
  1616.     }
  1617. }
  1618.